/******************************************************
 * @file page_manager.c
 * @author Destiny 
 * @brief 页面管理程序
 * @version 0.1
 * @date 2024-07-18
 *****************************************************/
/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdlib.h>

/* Private Includes ----------------------------------------------------------*/
#include <config.h>
#include <page_manager.h>
#include <render.h>

/* Private typedef -----------------------------------------------------------*/

/* Private Define ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

static PT_PageAction g_ptPageActionHead;
static T_PixelDatas g_tMousePixelDatas;

static char *g_strMouseIconName   = "/opt/icon/Menu/mouse.bmp";
static int g_iXres, g_iYres, g_iBpp;

/* Private Function Prototypes -----------------------------------------------*/

/**
 * @brief 注册页面结构体
 * 
 * @param ptPageAction 页面操作结构体指针
 * @return int 成功：0;失败：其他
*/
int RegisterPageAction(PT_PageAction ptPageAction)
{
	PT_PageAction ptTmp;

	if (!g_ptPageActionHead)
	{
		g_ptPageActionHead   = ptPageAction;
		ptPageAction->ptNext = NULL;
	}
	else
	{
		ptTmp = g_ptPageActionHead;
		while (ptTmp->ptNext)
		{
			ptTmp = ptTmp->ptNext;
		}
		ptTmp->ptNext	  = ptPageAction;
		ptPageAction->ptNext = NULL;
	}

	return 0;
}

/**
 * @brief 显示所有已注册的页面名称 
*/
void ShowPages(void)
{
	int i = 0;
	PT_PageAction ptTmp = g_ptPageActionHead;

	while (ptTmp)
	{
		printf("%02d %s\n", i++, ptTmp->name);
		ptTmp = ptTmp->ptNext;
	}
}
/*返回指定名称的页面*/

/**
 * @brief 返回指定名称的页面结构体
 * 
 * @param pcName 名称
 * @return PT_PageAction 页面操作结构体指针
*/
PT_PageAction Page(char *pcName)
{
	PT_PageAction ptTmp = g_ptPageActionHead;
	
	while (ptTmp)
	{
		if (strcmp(ptTmp->name, pcName) == 0)
		{
			return ptTmp;
		}
		ptTmp = ptTmp->ptNext;
	}
	return NULL;
}

/**
 * @brief 依据页面名称得到页面ID
 * 
 * @param strName 页面名称
 * @return int 成功：页面id;失败：其他
*/
int ID(char *strName)
{
	return (int)(strName[0]) + (int)(strName[1]) + (int)(strName[2]) + (int)(strName[3]);
}

/**
 * @brief 生成页面数据
 * 
 * @param ptPageLayout 页面布局信息
 * @param ptVideoMem 显示缓冲
 * @return int 成功：0;失败：其他
*/
int GeneratePage(PT_PageLayout ptPageLayout, PT_VideoMem ptVideoMem)
{
	T_PixelDatas tOriginIconPixelDatas;
	T_PixelDatas tIconPixelDatas;
	int iError;
	char* pcRet;
	PT_Layout atLayout = ptPageLayout->atLayout;
	/*如果页面数据已生成则返回*/
	if (ptVideoMem->ePicState == PS_GENERATED)
	{
		return 0;
	}
	/*1、将缓冲区设为背景色*/
	ClearVideoMem(ptVideoMem, g_BackGroundColor);
	tIconPixelDatas.iBpp          = ptPageLayout->iBpp;
	/*2、为图标文件分配数据缓冲区*/
	tIconPixelDatas.aucPixelDatas = malloc(ptPageLayout->iMaxTotalBytes);
	if (tIconPixelDatas.aucPixelDatas == NULL)
	{
		return -1;
	}
	/*3、遍历布局*/
	while (atLayout->strIconName)
	{
		pcRet = strchr(atLayout->strIconName,':');
		if(!pcRet)  /*为图标数据*/
		{
			/*得到指定图标原始图像数据*/
			iError = GetPixelDatasFrmFile(atLayout->strIconName, &tOriginIconPixelDatas);
			if (iError)
			{
				DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"GetPixelDatasFrmFile %s error!\n", atLayout->strIconName);
				free(tIconPixelDatas.aucPixelDatas);
				return -1;
			}
			/*确定图标显示大小*/
			tIconPixelDatas.iHeight = atLayout->iBotRightY - atLayout->iTopLeftY + 1;
			tIconPixelDatas.iWidth  = atLayout->iBotRightX - atLayout->iTopLeftX+ 1;
			tIconPixelDatas.iLineBytes  = tIconPixelDatas.iWidth * tIconPixelDatas.iBpp / 8;
			tIconPixelDatas.iTotalBytes = tIconPixelDatas.iLineBytes * tIconPixelDatas.iHeight;
			/*图标缩放到指定大小*/
			PicZoom(&tOriginIconPixelDatas, &tIconPixelDatas);
			/*将图标显示在缓冲区指定位置*/
			PicMerge(atLayout->iTopLeftX, atLayout->iTopLeftY, &tIconPixelDatas, &ptVideoMem->tPixelDatas);
			/*释放原始图标数据*/
			FreePixelDatasFrmFile(&tOriginIconPixelDatas);
			atLayout++;
		}
		else  /*为名称数据*/
		{
			SetFontSize(atLayout->iBotRightY - atLayout->iTopLeftY - 5);
			//DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"%s %s\n",atLayout->strIconName,pcRet+1);
			MergerStringToCenterOfRectangleInVideoMem(atLayout->iTopLeftX,atLayout->iTopLeftY,atLayout->iBotRightX,\
			atLayout->iBotRightY,(uint8_t*)pcRet+1,ptVideoMem);
			atLayout++;
		}
	}
	/*4、释放图标缓冲区*/
	free(tIconPixelDatas.aucPixelDatas);			
	/*5、将页面状态标记为生成结束*/
	ptVideoMem->ePicState = PS_GENERATED;
	return 0;
}

/**
 * @brief 计算两时间间隔，单位为ms
 * 
 * @param tTimeStart 前
 * @param tTimeEnd   后
 * @return int       间隔
*/
int TimeMSBetween(struct timeval tTimeStart, struct timeval tTimeEnd)
{
	int iMS;
	iMS = (tTimeEnd.tv_sec - tTimeStart.tv_sec) * 1000 + (tTimeEnd.tv_usec - tTimeStart.tv_usec) / 1000;
	return iMS;
}

/**
 * @brief 根据触摸屏输入数据，确定被选择的图标，返回其索引值(连续的两个索引表示同一个图标)
 * 
 * @param ptPageLayout 
 * @param ptInputEvent 
 * @return int 成功：被选择的图标索引;失败：-1
*/
int GenericGetInputEvent(PT_PageLayout ptPageLayout, PT_InputEvent ptInputEvent)
{
	T_InputEvent tInputEvent;
	int iRet;
	int i = 0;
	PT_Layout atLayout = ptPageLayout->atLayout;
	/*得到触摸屏输入数据*/
	iRet = GetInputEvent(&tInputEvent);
	if (iRet)
	{
		return -1;
	}
	/*如果不是触摸屏输入，则返回*/
	// if ((tInputEvent.iInputDevice != INPUT_DEVICE_TOUCHSCREEN))
	// {
	// 	return -1;
	// }
	*ptInputEvent = tInputEvent;
	/*遍历确定被选择图标索引*/
	while (atLayout[i].strIconName)
	{
		if ((tInputEvent.iX >= atLayout[i].iTopLeftX) && (tInputEvent.iX <= atLayout[i].iBotRightX) && \
			 (tInputEvent.iY >= atLayout[i].iTopLeftY) && (tInputEvent.iY <= atLayout[i].iBotRightY))
		{

			return i;
		}
		else
		{
			i++;
		}			
	}
	return -1;
}

/**
 * @brief 计算页面菜单栏分布位置
 * 
 * @param ptPageLayout 菜单栏分布信息
 * @param iNumMenu 菜单数量
*/
void CalculatePageMenusLayout(PT_PageLayout ptPageLayout,int iNumMenu)
{
    int iWidth;
    int iHeight;
    int iXres, iYres, iBpp;
    int iTmpTotalBytes;
    PT_Layout atLayout;
    int i;

    atLayout = ptPageLayout->atLayout;
    GetDispResolution(&iXres, &iYres, &iBpp);
    ptPageLayout->iBpp = iBpp;
    /*菜单栏*/
    if (iXres < iYres)
    {
        /*屏幕分辨率Y>X*/
        
        iWidth = iXres / iNumMenu;
        iHeight = iWidth;

        atLayout[0].iTopLeftY = 0;
        atLayout[0].iBotRightY = atLayout[0].iTopLeftY + iHeight - 1;
        atLayout[0].iTopLeftX = 0;
        atLayout[0].iBotRightX = atLayout[0].iTopLeftX + iWidth - 1;

        i = 1;
        while (atLayout[i].strIconName)
        {
            atLayout[i].iTopLeftY = 0;
            atLayout[i].iBotRightY = atLayout[i].iTopLeftY + iHeight - 1;
            atLayout[i].iTopLeftX = atLayout[i-1].iBotRightX + 1;
            atLayout[i].iBotRightX = atLayout[i].iTopLeftX + iWidth - 1;
            i++;
        }

    }
    else
    {

        iHeight = iYres / iNumMenu;
        iWidth = iHeight;

        atLayout[0].iTopLeftY = 0;
        atLayout[0].iBotRightY = atLayout[0].iTopLeftY + iHeight - 1;
        atLayout[0].iTopLeftX = 0;
        atLayout[0].iBotRightX = atLayout[0].iTopLeftX + iWidth - 1;

        i = 1;
        while (atLayout[i].strIconName)
        {
            atLayout[i].iTopLeftY = atLayout[i-1].iBotRightY + 1;
            atLayout[i].iBotRightY = atLayout[i].iTopLeftY + iHeight - 1;
            atLayout[i].iTopLeftX = 0;
            atLayout[i].iBotRightX = atLayout[i].iTopLeftX + iWidth - 1;
            i++;
        }
    }

    i = 0;
    /*计算得到最大iMaxTotalBytes，为分配空间做准备*/
    while (atLayout[i].strIconName)
    {
        iTmpTotalBytes = (atLayout[i].iBotRightX - atLayout[i].iTopLeftX + 1) * (atLayout[i].iBotRightY - atLayout[i].iTopLeftY + 1) * iBpp / 8;
        if (ptPageLayout->iMaxTotalBytes < iTmpTotalBytes)
        {
            ptPageLayout->iMaxTotalBytes = iTmpTotalBytes;
        }
        i++;
    }
}

/**
 * @brief 屏幕上显示鼠标箭头
 * 
 * @param ptInputEvent 输入事件信息
 * @param ptVideoMem 显示缓冲区
 * @return int 成功：0;失败：其他
*/
int MergeMouseToDisp(PT_InputEvent ptInputEvent,PT_VideoMem ptVideoMem)
{
	int iStartIY = ptInputEvent->iY;
	int iStartIX = ptInputEvent->iX;
	int iMaxIY   = g_iYres-g_tMousePixelDatas.iHeight -1;
	int iMaxIX   = g_iXres-g_tMousePixelDatas.iWidth - 1;
    iStartIY = (iStartIY < 0)? 0 :((iStartIY > iMaxIY)? iMaxIY : iStartIY);
	iStartIX = (iStartIX < 0)? 0 :((iStartIX > iMaxIX)? iMaxIX : iStartIX);
	PicMerge(iStartIX,iStartIY,&g_tMousePixelDatas,&ptVideoMem->tPixelDatas);
	return 0;
}

/**
 * @brief 得到鼠标箭头数据，并缩放为指定大小
 * 
 * @return int 成功：0;失败：其他
*/
static int GetMousePixelDatas()
{
	T_PixelDatas tTemp;
	int iError;
	iError = GetPixelDatasFrmFile(g_strMouseIconName,&tTemp);
	if(iError < 0)
	{
		DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"can't get Mouse icon datas\r\n");
		return -1;
	}
	g_tMousePixelDatas.iBpp          = tTemp.iBpp;
	g_tMousePixelDatas.iHeight       = 20;
	g_tMousePixelDatas.iWidth        = 10;
	g_tMousePixelDatas.iLineBytes    = g_tMousePixelDatas.iWidth*g_tMousePixelDatas.iBpp/8;
	g_tMousePixelDatas.iTotalBytes   = g_tMousePixelDatas.iLineBytes * g_tMousePixelDatas.iHeight;
	g_tMousePixelDatas.aucPixelDatas = malloc(g_tMousePixelDatas.iTotalBytes);
	if(!g_tMousePixelDatas.aucPixelDatas)
	{
		DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"can't malloc Memory for Mouse icon datas\r\n");
		return -1;
	}
	iError = PicZoom(&tTemp,&g_tMousePixelDatas);
	if(iError < 0)
	{
		DBG_PRINTF(DLOG_LVL_ERROR,DLOG_TAG,"PicZoom Mouse icon error!\r\n");
		return -1;
	}
	FreePixelDatasFrmFile(&tTemp);
	return 0;
}

/**
 * @brief 页面初始化
 * 
 * @return int 成功：0;失败：其他
*/
int PagesInit(void)
{
	int iError;
	iError = MainPageInit();
	iError |= BrowsePageInit();
	iError |= ReaderPageInit();
	iError |= CameraPageInit();
	iError |= ImagePageInit();
	iError |= SmartHomePageInit();
	iError |= MnistPageInit();
	iError |= GetMousePixelDatas();
	GetDispResolution(&g_iXres, &g_iYres, &g_iBpp);
	return iError;
}

/**
 * @brief 退出页面，释放图像数据内存
*/
void PagesExit(void)
{
	FreePixelDatasFrmFile(&g_tMousePixelDatas);
}
